/**
 * 
 */
package au.edu.swin.videoshop.ejb.bean;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import au.edu.swin.videoshop.bean.Classification;
import au.edu.swin.videoshop.bean.Customer;
import au.edu.swin.videoshop.bean.MediumType;
import au.edu.swin.videoshop.bean.Rental;
import au.edu.swin.videoshop.bean.RentalStatus;
import au.edu.swin.videoshop.bean.Reservation;
import au.edu.swin.videoshop.bean.ReservationStatus;
import au.edu.swin.videoshop.bean.Staff;
import au.edu.swin.videoshop.bean.StaffRole;
import au.edu.swin.videoshop.bean.StaffSession;
import au.edu.swin.videoshop.bean.Store;
import au.edu.swin.videoshop.bean.Title;
import au.edu.swin.videoshop.bean.TitleCategory;
import au.edu.swin.videoshop.bean.TitleCopy;
import au.edu.swin.videoshop.bean.TitleMedium;
import au.edu.swin.videoshop.persistence.CustomerEntity;
import au.edu.swin.videoshop.persistence.RentalEntity;
import au.edu.swin.videoshop.persistence.ReservationEntity;
import au.edu.swin.videoshop.persistence.StaffEntity;
import au.edu.swin.videoshop.persistence.StaffSessionEntity;
import au.edu.swin.videoshop.persistence.StoreEntity;
import au.edu.swin.videoshop.persistence.TitleCategoryEntity;
import au.edu.swin.videoshop.persistence.TitleCopyEntity;
import au.edu.swin.videoshop.persistence.TitleEntity;
import au.edu.swin.videoshop.persistence.TitleMediumEntity;

/**
 * @author julie
 *
 */
public class TransferService {

	private static class TransferObjectCache {
		private Map mCacheData = new HashMap();
		
		private Map getCache(Class clazz) {
			if (mCacheData.containsKey(clazz)) {
				return (Map)mCacheData.get(clazz);
			}
			else {
				Map data = new HashMap();
				mCacheData.put(clazz, data);
				return data;
			}
		}
		
		public boolean contains(Class clazz, Object id) {
			return getCache(clazz).containsKey(id);
		}
		
		public Object getValue(Class clazz, Object id) {
			return getCache(clazz).get(id);
		}
		
		public void cache(Object id, Object obj) {
			getCache(obj.getClass()).put(id, obj);
		}
	}
	
	private TransferObjectCache mCache;
	
	public TransferService() {
		mCache = new TransferObjectCache();
	}
	
	public TitleCategory toTitleCategoryTransferObject(TitleCategoryEntity categoryEntity) {
		Long id = categoryEntity.getTitleCategoryId();
		if (mCache.contains(TitleCategory.class, id)) {
			return (TitleCategory)mCache.getValue(TitleCategory.class, id);
		}
		else {
			TitleCategory category = new TitleCategory();
			category.setTitleCategoryId(id);
			
			mCache.cache(id, category);
			
			category.setCategoryName(categoryEntity.getCategoryName());
			category.setDescription(categoryEntity.getDescription());

			return category;
		}
	}
	
	public List toTitleCategoryTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			TitleCategoryEntity categoryEntity = (TitleCategoryEntity)i.next();
			retVal.add(toTitleCategoryTransferObject(categoryEntity));
		}
		
		return retVal;
	}
	
	private Title toTitleTransferObject(TitleEntity titleEntity) {
		Long id = titleEntity.getTitleId();
		if (mCache.contains(Title.class, id)) {
			return (Title)mCache.getValue(Title.class, id);
		}
		else {
			Title title = new Title();
			title.setTitleId(id);
			
			mCache.cache(id, title);
			
			title.setClassification(Classification.getInstance(titleEntity.getClassification()));
			title.setDescription(titleEntity.getDescription());
			title.setTitleName(titleEntity.getTitleName());
			title.setYear(titleEntity.getYear());

			title.setCategory(toTitleCategoryTransferObject(titleEntity.getCategory()));
			title.setMedia(toTitleMediumTransferObjectList(titleEntity.getMedia()));

			return title;
		}
	}
	
	public List toTitleTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			TitleEntity titleEntity = (TitleEntity)i.next();
			retVal.add(toTitleTransferObject(titleEntity));
		}
		
		return retVal;
	}

	private TitleMedium toTitleMediumTransferObject(TitleMediumEntity mediumEntity) {
		Long id = mediumEntity.getTitleMediumId();
		if (mCache.contains(TitleMedium.class, id)) {
			return (TitleMedium)mCache.getValue(TitleMedium.class, id);
		}
		else {
			TitleMedium medium = new TitleMedium();
			medium.setTitleMediumId(id);
			
			mCache.cache(id, medium);
			
			medium.setMaxRentalPeriod(mediumEntity.getMaxRentalPeriod());
			medium.setMediumType(MediumType.getInstance(mediumEntity.getMediumType()));
			medium.setPenaltyRate(mediumEntity.getPenaltyRate());
			medium.setRentalRate(mediumEntity.getRentalRate());
			
			medium.setTitle(toTitleTransferObject(mediumEntity.getTitle()));
			medium.setCopies(toTitleCopyTransferObjectList(mediumEntity.getCopies()));
			
			return medium;
		}
	}
	
	private List toTitleMediumTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			TitleMediumEntity mediumEntity = (TitleMediumEntity)i.next();
			retVal.add(toTitleMediumTransferObject(mediumEntity));
		}
		
		return retVal;
	}
	
	public TitleCopy toTitleCopyTransferObject(TitleCopyEntity copyEntity) {
		String id = copyEntity.getTitleCopyId();
		if (mCache.contains(TitleCopy.class, id)) {
			return (TitleCopy)mCache.getValue(TitleCopy.class, id);
		}
		else {
			TitleCopy copy = new TitleCopy();
			copy.setTitleCopyId(id);
			
			mCache.cache(id, copy);
			
			copy.setMedium(toTitleMediumTransferObject(copyEntity.getMedium()));
			copy.setStore(toStoreTransferObject(copyEntity.getStore()));
			
			return copy;
		}
	}
	
	public List toTitleCopyTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			TitleCopyEntity copyEntity = (TitleCopyEntity)i.next();
			retVal.add(toTitleCopyTransferObject(copyEntity));
		}
		
		return retVal;
	}
	
	public Rental toRentalTransferObject(RentalEntity rentalEntity) {
		Long id = rentalEntity.getRentalId();
		if (mCache.contains(Rental.class, id)) {
			return (Rental)mCache.getValue(Rental.class, id);
		}
		else {
			Rental rental = new Rental();
			rental.setRentalId(id);
		
			mCache.cache(id, rental);
			
			rental.setRentalDate(rentalEntity.getRentalDate());
			rental.setDueDate(rentalEntity.getDueDate());
			rental.setReturnDate(rentalEntity.getReturnDate());
			rental.setFirstCharge(rentalEntity.getFirstCharge());
			rental.setFinalCharge(rentalEntity.getFinalCharge());
			rental.setStatus(RentalStatus.getInstance(rentalEntity.getStatus()));
		
			rental.setTitleCopy(toTitleCopyTransferObject(rentalEntity.getTitleCopy()));
			rental.setCustomer(toCustomerTransferObject(rentalEntity.getCustomer()));
			rental.setStaff(toStaffTransferObject(rentalEntity.getStaff()));

			return rental;
		}
	}
	
	public List toRentalTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			RentalEntity rentalEntity = (RentalEntity)i.next();
			retVal.add(toRentalTransferObject(rentalEntity));
		}
		
		return retVal;
	}
	
	private Reservation toReservationTransferObject(ReservationEntity reservationEntity) {
		Long id = reservationEntity.getReservationId();
		if (mCache.contains(Reservation.class, id)) {
			return (Reservation)mCache.getValue(Reservation.class, id);
		}
		else {
			Reservation reservation = new Reservation();
			reservation.setReservationId(id);
		
			mCache.cache(id, reservation);
			
			reservation.setExpiryDate(reservationEntity.getExpiryDate());
			reservation.setReservationDate(reservationEntity.getReservationDate());
			reservation.setStatus(ReservationStatus.getInstance(reservationEntity.getStatus()));
			
			reservation.setMedium(toTitleMediumTransferObject(reservationEntity.getMedium()));
			reservation.setCustomer(toCustomerTransferObject(reservationEntity.getCustomer()));
			reservation.setStore(toStoreTransferObject(reservationEntity.getStore()));
			
			return reservation;
		}
	}
	
	public List toReservationTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			ReservationEntity reservationEntity = (ReservationEntity)i.next();
			retVal.add(toReservationTransferObject(reservationEntity));
		}
		
		return retVal;
	}
	
	public Store toStoreTransferObject(StoreEntity storeEntity) {
		Long id = storeEntity.getStoreId();
		if (mCache.contains(Store.class, id)) {
			return (Store)mCache.getValue(Store.class, id);
		}
		else {
			Store store = new Store();
			store.setStoreId(id);
			
			mCache.cache(id, store);
			
			store.setAddress(storeEntity.getAddress());
			store.setStoreName(storeEntity.getStoreName());

			return store;
		}
	}
	
	public List toStoreTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			StoreEntity storeEntity = (StoreEntity)i.next();
			retVal.add(toStoreTransferObject(storeEntity));
		}
		
		return retVal;
	}
	
	public Customer toCustomerTransferObject(CustomerEntity customerEntity) {
		Long id = customerEntity.getCustomerId();
		if (mCache.contains(Customer.class, id)) {
			return (Customer)mCache.getValue(Customer.class, id);
		}
		else {
			Customer customer = new Customer();
			customer.setCustomerId(id);
			
			mCache.cache(id, customer);
		
			customer.setFirstName(customerEntity.getFirstName());
			customer.setLastName(customerEntity.getLastName());
			customer.setContactNumber(customerEntity.getContactNumber());
			customer.setEmailAddress(customerEntity.getEmailAddress());
			customer.setAddress(customerEntity.getAddress());
			customer.setCredit(customerEntity.getCredit());
			customer.setUserName(customerEntity.getUserName());
			customer.setPassword(customerEntity.getPassword());
			
			return customer;
		}
	}
	
	public List toCustomerTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			CustomerEntity customerEntity = (CustomerEntity)i.next();
			retVal.add(toCustomerTransferObject(customerEntity));
		}
		
		return retVal;
	}
	
	public StaffSession toStaffSessionTransferObject(StaffSessionEntity sessionEntity) {
		StaffSession staffSession = new StaffSession();
		staffSession.setSessionId(sessionEntity.getSessionId());
		staffSession.setLoginTime(sessionEntity.getLoginTime());
		staffSession.setLogoutTime(sessionEntity.getLogoutTime());
		
		return staffSession;
	}
	
	public Staff toStaffTransferObject(StaffEntity staffEntity) {
		Long id = staffEntity.getStaffId();
		if (mCache.contains(Staff.class, id)) {
			return (Staff)mCache.getValue(Staff.class, id);
		}
		else {
			Staff staff = new Staff();
			staff.setStaffId(id);
			
			mCache.cache(id, staff);

			staff.setFirstName(staffEntity.getFirstName());
			staff.setLastName(staffEntity.getLastName());
			staff.setContactNumber(staffEntity.getContactNumber());
			staff.setEmailAddress(staffEntity.getEmailAddress());
			staff.setAddress(staffEntity.getAddress());
			
			if (staffEntity.getStore() != null) {
				staff.setStore(toStoreTransferObject(staffEntity.getStore()));
			}
			
			if (staffEntity.getSupervisor() != null) {
				staff.setSupervisor(toStaffTransferObject(staffEntity.getSupervisor()));
			}
			
			staff.setUserName(staffEntity.getUserName());
			staff.setPassword(staffEntity.getPassword());
			staff.setRole(StaffRole.getInstance(staffEntity.getRole()));
			
			return staff;
		}
	}
	
	public List toStaffTransferObjectList(List list) {
		List retVal = new ArrayList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			StaffEntity staffEntity = (StaffEntity)i.next();
			retVal.add(toStaffTransferObject(staffEntity));
		}
		
		return retVal;
	}
	
	
	
	
	
	
	
	public TitleCategoryEntity toTitleCategoryEntity(TitleCategory category) {
		TitleCategoryEntity categoryEntity = new TitleCategoryEntity();
		categoryEntity.setTitleCategoryId(category.getTitleCategoryId());
		categoryEntity.setCategoryName(category.getCategoryName());
		categoryEntity.setDescription(category.getDescription());
		
		return categoryEntity;
	}
	
	private TitleEntity toSimpleTitleEntity(Title title) {
		TitleEntity titleEntity = new TitleEntity();
		titleEntity.setTitleId(title.getTitleId());
		titleEntity.setClassification(title.getClassification().getName());
		titleEntity.setDescription(title.getDescription());
		titleEntity.setTitleName(title.getTitleName());
		titleEntity.setYear(title.getYear());
		
		return titleEntity;
	}
	
	private TitleMediumEntity toSimpleTitleMediumEntity(TitleMedium medium) {
		TitleMediumEntity mediumEntity = new TitleMediumEntity();
		mediumEntity.setTitleMediumId(medium.getTitleMediumId());
		mediumEntity.setMaxRentalPeriod(medium.getMaxRentalPeriod());
		mediumEntity.setMediumType(medium.getMediumType().getName());
		mediumEntity.setPenaltyRate(medium.getPenaltyRate());
		mediumEntity.setRentalRate(medium.getRentalRate());
		
		return mediumEntity;
	}
	
	private TitleCopyEntity toSimpleTitleCopyEntity(TitleCopy copy) {
		TitleCopyEntity copyEntity = new TitleCopyEntity();
		copyEntity.setTitleCopyId(copy.getTitleCopyId());
		
		return copyEntity;
	}	
	
	public TitleEntity toTitleEntity(Title title) {
		TitleEntity titleEntity = toSimpleTitleEntity(title);
		
		TitleCategoryEntity categoryEntity = toTitleCategoryEntity(title.getCategory());
		titleEntity.setCategory(categoryEntity);
		
		List media = new ArrayList();
		if (title.getMedia() != null) {
			for (Iterator i = title.getMedia().iterator(); i.hasNext();) {
				TitleMedium medium = (TitleMedium)i.next();
				
				TitleMediumEntity mediumEntity = toSimpleTitleMediumEntity(medium);
				mediumEntity.setTitle(titleEntity);
				
				List copies = new ArrayList();
				if (medium.getCopies() != null) {
					for (Iterator j = medium.getCopies().iterator(); j.hasNext();) {
						TitleCopy copy = (TitleCopy)j.next();
						
						TitleCopyEntity copyEntity = toSimpleTitleCopyEntity(copy);
						StoreEntity storeEntity = toStoreEntity(copy.getStore());;
					
						copyEntity.setStore(storeEntity);
						copyEntity.setMedium(mediumEntity);
						
						copies.add(copyEntity);
					}
				}
				
				mediumEntity.setCopies(copies);
				
				media.add(mediumEntity);
			}
		}
		
		titleEntity.setMedia(media);

		return titleEntity;
	}
	
	

	public RentalEntity toRentalEntity(Rental rental) {
		RentalEntity rentalEntity = new RentalEntity();
		rentalEntity.setRentalId(rental.getRentalId());
		rentalEntity.setRentalDate(rental.getRentalDate());
		rentalEntity.setDueDate(rental.getDueDate());
		rentalEntity.setReturnDate(rental.getReturnDate());
		rentalEntity.setFirstCharge(rental.getFirstCharge());
		rentalEntity.setFinalCharge(rental.getFinalCharge());
		rentalEntity.setStatus(rental.getStatus().getName());
		
		rentalEntity.setTitleCopy(toSimpleTitleCopyEntity(rental.getTitleCopy()));
		rentalEntity.setCustomer(toCustomerEntity(rental.getCustomer()));
		rentalEntity.setStaff(toStaffEntity(rental.getStaff()));
		

		return rentalEntity;
	}
	
	public ReservationEntity toReservationEntity(Reservation reservation) {
		ReservationEntity reservationEntity = new ReservationEntity();
		reservationEntity.setReservationId(reservation.getReservationId());
		reservationEntity.setExpiryDate(reservation.getExpiryDate());
		reservationEntity.setReservationDate(reservation.getReservationDate());
		reservationEntity.setStatus(reservation.getStatus().getName());
		
		reservationEntity.setMedium(toSimpleTitleMediumEntity(reservation.getMedium()));
		reservationEntity.setCustomer(toCustomerEntity(reservation.getCustomer()));
		reservationEntity.setStore(toStoreEntity(reservation.getStore()));
		
		return reservationEntity;
	}
	
	public CustomerEntity toCustomerEntity(Customer customer) {
		CustomerEntity customerEntity = new CustomerEntity();
		customerEntity.setCustomerId(customer.getCustomerId());
		customerEntity.setFirstName(customer.getFirstName());
		customerEntity.setLastName(customer.getLastName());
		customerEntity.setContactNumber(customer.getContactNumber());
		customerEntity.setEmailAddress(customer.getEmailAddress());
		customerEntity.setAddress(customer.getAddress());
		customerEntity.setCredit(customer.getCredit());
		customerEntity.setUserName(customer.getUserName());
		customerEntity.setPassword(customer.getPassword());
		
		return customerEntity;
	}
	
	public StaffEntity toStaffEntity(Staff staff) {
		StaffEntity staffEntity = new StaffEntity();
		staffEntity.setStaffId(staff.getStaffId());
		staffEntity.setFirstName(staff.getFirstName());
		staffEntity.setLastName(staff.getLastName());
		staffEntity.setContactNumber(staff.getContactNumber());
		staffEntity.setEmailAddress(staff.getEmailAddress());
		staffEntity.setAddress(staff.getAddress());
		if (staff.getStore() != null) {
			staffEntity.setStore(toStoreEntity(staff.getStore()));
		}
		if (staff.getSupervisor() != null) {
			staffEntity.setSupervisor(toStaffEntity(staff.getSupervisor()));
		}

		staffEntity.setUserName(staff.getUserName());
		staffEntity.setPassword(staff.getPassword());
		staffEntity.setRole(staff.getRole().getName());
		
		return staffEntity;
	}
	
	public StaffSessionEntity toStaffSessionEntity(StaffSession session) {
		StaffSessionEntity staffSessionEntity = new StaffSessionEntity();
		staffSessionEntity.setSessionId(session.getSessionId());
		staffSessionEntity.setLoginTime(session.getLoginTime());
		staffSessionEntity.setLogoutTime(session.getLogoutTime());
		
		return staffSessionEntity;
	}

	public StoreEntity toStoreEntity(Store store) {
		StoreEntity storeEntity = new StoreEntity();
		storeEntity.setStoreId(store.getStoreId());
		storeEntity.setAddress(store.getAddress());
		storeEntity.setStoreName(store.getStoreName());
		
		return storeEntity;
	}
}
